librelane 2.4.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of librelane might be problematic. Click here for more details.

Files changed (170) hide show
  1. librelane/__init__.py +38 -0
  2. librelane/__main__.py +479 -0
  3. librelane/__version__.py +43 -0
  4. librelane/common/__init__.py +63 -0
  5. librelane/common/cli.py +75 -0
  6. librelane/common/drc.py +246 -0
  7. librelane/common/generic_dict.py +319 -0
  8. librelane/common/metrics/__init__.py +35 -0
  9. librelane/common/metrics/__main__.py +413 -0
  10. librelane/common/metrics/library.py +354 -0
  11. librelane/common/metrics/metric.py +186 -0
  12. librelane/common/metrics/util.py +279 -0
  13. librelane/common/misc.py +456 -0
  14. librelane/common/ring_buffer.py +63 -0
  15. librelane/common/tcl.py +80 -0
  16. librelane/common/toolbox.py +549 -0
  17. librelane/common/tpe.py +41 -0
  18. librelane/common/types.py +116 -0
  19. librelane/config/__init__.py +32 -0
  20. librelane/config/__main__.py +155 -0
  21. librelane/config/config.py +1025 -0
  22. librelane/config/flow.py +490 -0
  23. librelane/config/pdk_compat.py +255 -0
  24. librelane/config/preprocessor.py +464 -0
  25. librelane/config/removals.py +45 -0
  26. librelane/config/variable.py +743 -0
  27. librelane/container.py +285 -0
  28. librelane/env_info.py +320 -0
  29. librelane/examples/spm/config.yaml +33 -0
  30. librelane/examples/spm/pin_order.cfg +14 -0
  31. librelane/examples/spm/src/impl.sdc +73 -0
  32. librelane/examples/spm/src/signoff.sdc +68 -0
  33. librelane/examples/spm/src/spm.v +73 -0
  34. librelane/examples/spm/verify/spm_tb.v +106 -0
  35. librelane/examples/spm-user_project_wrapper/SPM_example.v +286 -0
  36. librelane/examples/spm-user_project_wrapper/base_sdc_file.sdc +145 -0
  37. librelane/examples/spm-user_project_wrapper/config-tut.json +12 -0
  38. librelane/examples/spm-user_project_wrapper/config.json +13 -0
  39. librelane/examples/spm-user_project_wrapper/defines.v +66 -0
  40. librelane/examples/spm-user_project_wrapper/template.def +7656 -0
  41. librelane/examples/spm-user_project_wrapper/user_project_wrapper.v +123 -0
  42. librelane/flows/__init__.py +24 -0
  43. librelane/flows/builtins.py +18 -0
  44. librelane/flows/classic.py +327 -0
  45. librelane/flows/cli.py +463 -0
  46. librelane/flows/flow.py +1049 -0
  47. librelane/flows/misc.py +71 -0
  48. librelane/flows/optimizing.py +179 -0
  49. librelane/flows/sequential.py +367 -0
  50. librelane/flows/synth_explore.py +173 -0
  51. librelane/help/__main__.py +39 -0
  52. librelane/logging/__init__.py +40 -0
  53. librelane/logging/logger.py +323 -0
  54. librelane/open_pdks_rev +1 -0
  55. librelane/plugins.py +21 -0
  56. librelane/py.typed +0 -0
  57. librelane/scripts/base.sdc +80 -0
  58. librelane/scripts/klayout/Readme.md +2 -0
  59. librelane/scripts/klayout/open_design.py +63 -0
  60. librelane/scripts/klayout/render.py +121 -0
  61. librelane/scripts/klayout/stream_out.py +176 -0
  62. librelane/scripts/klayout/xml_drc_report_to_json.py +45 -0
  63. librelane/scripts/klayout/xor.drc +120 -0
  64. librelane/scripts/magic/Readme.md +1 -0
  65. librelane/scripts/magic/common/read.tcl +114 -0
  66. librelane/scripts/magic/def/antenna_check.tcl +35 -0
  67. librelane/scripts/magic/def/mag.tcl +19 -0
  68. librelane/scripts/magic/def/mag_gds.tcl +79 -0
  69. librelane/scripts/magic/drc.tcl +78 -0
  70. librelane/scripts/magic/extract_spice.tcl +98 -0
  71. librelane/scripts/magic/gds/drc_batch.tcl +74 -0
  72. librelane/scripts/magic/gds/erase_box.tcl +32 -0
  73. librelane/scripts/magic/gds/extras_mag.tcl +45 -0
  74. librelane/scripts/magic/gds/mag_with_pointers.tcl +31 -0
  75. librelane/scripts/magic/get_bbox.tcl +11 -0
  76. librelane/scripts/magic/lef/extras_maglef.tcl +61 -0
  77. librelane/scripts/magic/lef/maglef.tcl +26 -0
  78. librelane/scripts/magic/lef.tcl +57 -0
  79. librelane/scripts/magic/open.tcl +28 -0
  80. librelane/scripts/magic/wrapper.tcl +21 -0
  81. librelane/scripts/netgen/setup.tcl +28 -0
  82. librelane/scripts/odbpy/apply_def_template.py +49 -0
  83. librelane/scripts/odbpy/cell_frequency.py +107 -0
  84. librelane/scripts/odbpy/check_antenna_properties.py +116 -0
  85. librelane/scripts/odbpy/contextualize.py +109 -0
  86. librelane/scripts/odbpy/defutil.py +573 -0
  87. librelane/scripts/odbpy/diodes.py +373 -0
  88. librelane/scripts/odbpy/disconnected_pins.py +305 -0
  89. librelane/scripts/odbpy/eco_buffer.py +181 -0
  90. librelane/scripts/odbpy/eco_diode.py +139 -0
  91. librelane/scripts/odbpy/filter_unannotated.py +100 -0
  92. librelane/scripts/odbpy/io_place.py +482 -0
  93. librelane/scripts/odbpy/ioplace_parser/__init__.py +23 -0
  94. librelane/scripts/odbpy/ioplace_parser/parse.py +147 -0
  95. librelane/scripts/odbpy/label_macro_pins.py +277 -0
  96. librelane/scripts/odbpy/lefutil.py +97 -0
  97. librelane/scripts/odbpy/placers.py +162 -0
  98. librelane/scripts/odbpy/power_utils.py +397 -0
  99. librelane/scripts/odbpy/random_place.py +57 -0
  100. librelane/scripts/odbpy/reader.py +250 -0
  101. librelane/scripts/odbpy/remove_buffers.py +173 -0
  102. librelane/scripts/odbpy/snap_to_grid.py +57 -0
  103. librelane/scripts/odbpy/wire_lengths.py +93 -0
  104. librelane/scripts/openroad/antenna_check.tcl +20 -0
  105. librelane/scripts/openroad/antenna_repair.tcl +31 -0
  106. librelane/scripts/openroad/basic_mp.tcl +24 -0
  107. librelane/scripts/openroad/buffer_list.tcl +10 -0
  108. librelane/scripts/openroad/common/dpl.tcl +24 -0
  109. librelane/scripts/openroad/common/dpl_cell_pad.tcl +26 -0
  110. librelane/scripts/openroad/common/grt.tcl +32 -0
  111. librelane/scripts/openroad/common/io.tcl +540 -0
  112. librelane/scripts/openroad/common/pdn_cfg.tcl +135 -0
  113. librelane/scripts/openroad/common/resizer.tcl +103 -0
  114. librelane/scripts/openroad/common/set_global_connections.tcl +78 -0
  115. librelane/scripts/openroad/common/set_layer_adjustments.tcl +31 -0
  116. librelane/scripts/openroad/common/set_power_nets.tcl +30 -0
  117. librelane/scripts/openroad/common/set_rc.tcl +75 -0
  118. librelane/scripts/openroad/common/set_routing_layers.tcl +30 -0
  119. librelane/scripts/openroad/cts.tcl +80 -0
  120. librelane/scripts/openroad/cut_rows.tcl +24 -0
  121. librelane/scripts/openroad/dpl.tcl +24 -0
  122. librelane/scripts/openroad/drt.tcl +37 -0
  123. librelane/scripts/openroad/fill.tcl +30 -0
  124. librelane/scripts/openroad/floorplan.tcl +145 -0
  125. librelane/scripts/openroad/gpl.tcl +88 -0
  126. librelane/scripts/openroad/grt.tcl +30 -0
  127. librelane/scripts/openroad/gui.tcl +37 -0
  128. librelane/scripts/openroad/insert_buffer.tcl +127 -0
  129. librelane/scripts/openroad/ioplacer.tcl +67 -0
  130. librelane/scripts/openroad/irdrop.tcl +51 -0
  131. librelane/scripts/openroad/pdn.tcl +52 -0
  132. librelane/scripts/openroad/rcx.tcl +32 -0
  133. librelane/scripts/openroad/repair_design.tcl +70 -0
  134. librelane/scripts/openroad/repair_design_postgrt.tcl +48 -0
  135. librelane/scripts/openroad/rsz_timing_postcts.tcl +68 -0
  136. librelane/scripts/openroad/rsz_timing_postgrt.tcl +70 -0
  137. librelane/scripts/openroad/sta/check_macro_instances.tcl +53 -0
  138. librelane/scripts/openroad/sta/corner.tcl +393 -0
  139. librelane/scripts/openroad/tapcell.tcl +25 -0
  140. librelane/scripts/openroad/write_views.tcl +27 -0
  141. librelane/scripts/pyosys/construct_abc_script.py +177 -0
  142. librelane/scripts/pyosys/json_header.py +84 -0
  143. librelane/scripts/pyosys/synthesize.py +493 -0
  144. librelane/scripts/pyosys/ys_common.py +153 -0
  145. librelane/scripts/tclsh/hello.tcl +1 -0
  146. librelane/state/__init__.py +24 -0
  147. librelane/state/__main__.py +61 -0
  148. librelane/state/design_format.py +195 -0
  149. librelane/state/state.py +359 -0
  150. librelane/steps/__init__.py +61 -0
  151. librelane/steps/__main__.py +510 -0
  152. librelane/steps/checker.py +637 -0
  153. librelane/steps/common_variables.py +340 -0
  154. librelane/steps/cvc_rv.py +169 -0
  155. librelane/steps/klayout.py +509 -0
  156. librelane/steps/magic.py +576 -0
  157. librelane/steps/misc.py +160 -0
  158. librelane/steps/netgen.py +253 -0
  159. librelane/steps/odb.py +1088 -0
  160. librelane/steps/openroad.py +2460 -0
  161. librelane/steps/openroad_alerts.py +102 -0
  162. librelane/steps/pyosys.py +640 -0
  163. librelane/steps/step.py +1571 -0
  164. librelane/steps/tclstep.py +288 -0
  165. librelane/steps/verilator.py +222 -0
  166. librelane/steps/yosys.py +371 -0
  167. librelane-2.4.0.dist-info/METADATA +169 -0
  168. librelane-2.4.0.dist-info/RECORD +170 -0
  169. librelane-2.4.0.dist-info/WHEEL +4 -0
  170. librelane-2.4.0.dist-info/entry_points.txt +9 -0
@@ -0,0 +1,73 @@
1
+ set clock_port __VIRTUAL_CLK__
2
+ if { [info exists ::env(CLOCK_PORT)] } {
3
+ set port_count [llength $::env(CLOCK_PORT)]
4
+
5
+ if { $port_count == "0" } {
6
+ puts "\[WARNING] No CLOCK_PORT found. A dummy clock will be used."
7
+ } elseif { $port_count != "1" } {
8
+ puts "\[WARNING] Multi-clock files are not currently supported by the base SDC file. Only the first clock will be constrained."
9
+ }
10
+
11
+ if { $port_count > "0" } {
12
+ set ::clock_port [lindex $::env(CLOCK_PORT) 0]
13
+ }
14
+ }
15
+ set port_args [get_ports $clock_port]
16
+ puts "\[INFO] Using clock $clock_port…"
17
+ create_clock {*}$port_args -name $clock_port -period $::env(CLOCK_PERIOD)
18
+
19
+ set input_delay_value [expr $::env(CLOCK_PERIOD) * $::env(IO_DELAY_CONSTRAINT) / 100]
20
+ set output_delay_value [expr $::env(CLOCK_PERIOD) * $::env(IO_DELAY_CONSTRAINT) / 100]
21
+ puts "\[INFO] Setting output delay to: $output_delay_value"
22
+ puts "\[INFO] Setting input delay to: $input_delay_value"
23
+
24
+ set_max_fanout $::env(MAX_FANOUT_CONSTRAINT) [current_design]
25
+ if { [info exists ::env(MAX_TRANSITION_CONSTRAINT)] } {
26
+ set_max_transition $::env(MAX_TRANSITION_CONSTRAINT) [current_design]
27
+ }
28
+ if { [info exists ::env(MAX_CAPACITANCE_CONSTRAINT)] } {
29
+ set_max_capacitance $::env(MAX_CAPACITANCE_CONSTRAINT) [current_design]
30
+ }
31
+
32
+ set clk_input [get_port $clock_port]
33
+ set clk_indx [lsearch [all_inputs] $clk_input]
34
+ set all_inputs_wo_clk [lreplace [all_inputs] $clk_indx $clk_indx ""]
35
+
36
+ #set rst_input [get_port resetn]
37
+ #set rst_indx [lsearch [all_inputs] $rst_input]
38
+ #set all_inputs_wo_clk_rst [lreplace $all_inputs_wo_clk $rst_indx $rst_indx ""]
39
+ set all_inputs_wo_clk_rst $all_inputs_wo_clk
40
+
41
+ # correct resetn
42
+ set clocks [get_clocks $clock_port]
43
+
44
+ set_input_delay $input_delay_value -clock $clocks $all_inputs_wo_clk_rst
45
+ set_output_delay $output_delay_value -clock $clocks [all_outputs]
46
+
47
+ if { ![info exists ::env(SYNTH_CLK_DRIVING_CELL)] } {
48
+ set ::env(SYNTH_CLK_DRIVING_CELL) $::env(SYNTH_DRIVING_CELL)
49
+ }
50
+
51
+ set_driving_cell \
52
+ -lib_cell [lindex [split $::env(SYNTH_DRIVING_CELL) "/"] 0] \
53
+ -pin [lindex [split $::env(SYNTH_DRIVING_CELL) "/"] 1] \
54
+ $all_inputs_wo_clk_rst
55
+
56
+ set_driving_cell \
57
+ -lib_cell [lindex [split $::env(SYNTH_CLK_DRIVING_CELL) "/"] 0] \
58
+ -pin [lindex [split $::env(SYNTH_CLK_DRIVING_CELL) "/"] 1] \
59
+ $clk_input
60
+
61
+ set cap_load [expr $::env(OUTPUT_CAP_LOAD) / 1000.0]
62
+ puts "\[INFO] Setting load to: $cap_load"
63
+ set_load $cap_load [all_outputs]
64
+
65
+ puts "\[INFO] Setting clock uncertainty to: $::env(CLOCK_UNCERTAINTY_CONSTRAINT)"
66
+ set_clock_uncertainty $::env(CLOCK_UNCERTAINTY_CONSTRAINT) $clocks
67
+
68
+ puts "\[INFO] Setting clock transition to: $::env(CLOCK_TRANSITION_CONSTRAINT)"
69
+ set_clock_transition $::env(CLOCK_TRANSITION_CONSTRAINT) $clocks
70
+
71
+ puts "\[INFO] Setting timing derate to: $::env(TIME_DERATING_CONSTRAINT)%"
72
+ set_timing_derate -early [expr 1-[expr $::env(TIME_DERATING_CONSTRAINT) / 100]]
73
+ set_timing_derate -late [expr 1+[expr $::env(TIME_DERATING_CONSTRAINT) / 100]]
@@ -0,0 +1,68 @@
1
+ # Compared to the implementation SDC, the signoff SDC relaxes
2
+ # max capacitance and transition constraints. (Which are intentionally over-
3
+ # constrained for implementation to yield better results.)
4
+
5
+ set clock_port __VIRTUAL_CLK__
6
+ if { [info exists ::env(CLOCK_PORT)] } {
7
+ set port_count [llength $::env(CLOCK_PORT)]
8
+
9
+ if { $port_count == "0" } {
10
+ puts stderr "\[WARNING] No CLOCK_PORT found. A dummy clock will be used."
11
+ } elseif { $port_count != "1" } {
12
+ puts stderr "\[WARNING] Multi-clock files are not currently supported by the base SDC file. Only the first clock will be constrained."
13
+ }
14
+
15
+ if { $port_count > "0" } {
16
+ set ::clock_port [lindex $::env(CLOCK_PORT) 0]
17
+ }
18
+ }
19
+ set port_args [get_ports $clock_port]
20
+ puts "\[INFO] Using clock $clock_port…"
21
+ create_clock {*}$port_args -name $clock_port -period $::env(CLOCK_PERIOD)
22
+
23
+ set input_delay_value [expr $::env(CLOCK_PERIOD) * $::env(IO_DELAY_CONSTRAINT) / 100]
24
+ set output_delay_value [expr $::env(CLOCK_PERIOD) * $::env(IO_DELAY_CONSTRAINT) / 100]
25
+ puts "\[INFO] Setting output delay to: $output_delay_value"
26
+ puts "\[INFO] Setting input delay to: $input_delay_value"
27
+
28
+ set_max_fanout $::env(MAX_FANOUT_CONSTRAINT) [current_design]
29
+
30
+ set clk_input [get_port $clock_port]
31
+ set clk_indx [lsearch [all_inputs] $clk_input]
32
+ set all_inputs_wo_clk [lreplace [all_inputs] $clk_indx $clk_indx ""]
33
+
34
+ #set rst_input [get_port resetn]
35
+ #set rst_indx [lsearch [all_inputs] $rst_input]
36
+ #set all_inputs_wo_clk_rst [lreplace $all_inputs_wo_clk $rst_indx $rst_indx ""]
37
+ set all_inputs_wo_clk_rst $all_inputs_wo_clk
38
+
39
+ # correct resetn
40
+ set clocks [get_clocks $clock_port]
41
+
42
+ set_input_delay $input_delay_value -clock $clocks $all_inputs_wo_clk_rst
43
+ set_output_delay $output_delay_value -clock $clocks [all_outputs]
44
+
45
+ if { ![info exists ::env(SYNTH_CLK_DRIVING_CELL)] } {
46
+ set ::env(SYNTH_CLK_DRIVING_CELL) $::env(SYNTH_DRIVING_CELL)
47
+ }
48
+
49
+ set_driving_cell \
50
+ -lib_cell [lindex [split $::env(SYNTH_DRIVING_CELL) "/"] 0] \
51
+ -pin [lindex [split $::env(SYNTH_DRIVING_CELL) "/"] 1] \
52
+ $all_inputs_wo_clk_rst
53
+
54
+ set_driving_cell \
55
+ -lib_cell [lindex [split $::env(SYNTH_CLK_DRIVING_CELL) "/"] 0] \
56
+ -pin [lindex [split $::env(SYNTH_CLK_DRIVING_CELL) "/"] 1] \
57
+ $clk_input
58
+
59
+ set cap_load [expr $::env(OUTPUT_CAP_LOAD) / 1000.0]
60
+ puts "\[INFO] Setting load to: $cap_load"
61
+ set_load $cap_load [all_outputs]
62
+
63
+ puts "\[INFO] Setting clock uncertainty to: 0.1"
64
+ set_clock_uncertainty 0.1 $clocks
65
+
66
+ puts "\[INFO] Setting timing derate to: $::env(TIME_DERATING_CONSTRAINT)%"
67
+ set_timing_derate -early [expr 1-[expr $::env(TIME_DERATING_CONSTRAINT) / 100]]
68
+ set_timing_derate -late [expr 1+[expr $::env(TIME_DERATING_CONSTRAINT) / 100]]
@@ -0,0 +1,73 @@
1
+ // Copyright 2023 Efabless Corporation
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ // (Parameterized) Unsigned Serial/Parallel Multiplier:
16
+ // - Multiplicand x (Input bit-serially)
17
+ // - Multiplier a (All bits at the same time/Parallel)
18
+ // - Product y (Output bit-serial)
19
+ module spm #(parameter bits=32) (
20
+ input clk,
21
+ input rst,
22
+ input x,
23
+ input[bits-1: 0] a,
24
+ output y
25
+ );
26
+ wire[bits: 0] y_chain;
27
+ assign y_chain[0] = 0;
28
+ assign y = y_chain[bits];
29
+
30
+ wire[bits-1:0] a_flip;
31
+ genvar i;
32
+ generate
33
+ for (i = 0; i < bits; i = i + 1) begin : flip_block
34
+ assign a_flip[i] = a[bits - i - 1];
35
+ end
36
+ endgenerate
37
+
38
+ delayed_serial_adder dsa[bits-1:0](
39
+ .clk(clk),
40
+ .rst(rst),
41
+ .x(x),
42
+ .a(a_flip),
43
+ .y_in(y_chain[bits-1:0]),
44
+ .y_out(y_chain[bits:1])
45
+ );
46
+
47
+ endmodule
48
+
49
+ module delayed_serial_adder(
50
+ input clk,
51
+ input rst,
52
+ input x,
53
+ input a,
54
+ input y_in,
55
+ output reg y_out
56
+ );
57
+ reg last_carry;
58
+ wire last_carry_next;
59
+ wire y_out_next;
60
+
61
+ wire g = x & a;
62
+ assign {last_carry_next, y_out_next} = g + y_in + last_carry;
63
+
64
+ always @ (posedge clk or negedge rst) begin
65
+ if (!rst) begin
66
+ last_carry <= 1'b0;
67
+ y_out <= 1'b0;
68
+ end else begin
69
+ last_carry <= last_carry_next;
70
+ y_out <= y_out_next;
71
+ end
72
+ end
73
+ endmodule
@@ -0,0 +1,106 @@
1
+ // Copyright 2023 Efabless Corporation
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ module spm_tb;
16
+ localparam bits = 32;
17
+ reg clk;
18
+ reg rst;
19
+ reg load;
20
+ reg[bits-1:0] x;
21
+ reg[bits-1:0] a;
22
+
23
+ wire[bits-1:0] srx_value;
24
+ sreg #(bits) srx(
25
+ .clk(clk),
26
+ .rst(rst),
27
+ .direction(1'b1),
28
+ .serial_msb(1'b0),
29
+ .serial_lsb(1'b0),
30
+ .load(load),
31
+ .load_value(x),
32
+ .value(srx_value)
33
+ );
34
+
35
+ wire y;
36
+ wire [bits*2-1:0] y_value;
37
+ sreg #(bits * 2) sry(
38
+ .clk(clk),
39
+ .rst(rst),
40
+ .direction(1'b1),
41
+ .serial_msb(y),
42
+ .serial_lsb(1'b0),
43
+ .load(1'b0),
44
+ .load_value({(bits*2){1'b0}}),
45
+ .value(y_value)
46
+ );
47
+
48
+ spm dut(
49
+ .clk(clk),
50
+ .rst(rst),
51
+ .x(srx_value[0]),
52
+ .a(a),
53
+ .y(y)
54
+ );
55
+
56
+ always #1 clk = ~clk;
57
+
58
+ reg [bits*2-1:0] expected;
59
+
60
+ initial begin
61
+ $dumpvars(0, spm_tb);
62
+ for (integer i = 0; i < 20; i = i + 1) begin
63
+ clk = 0;
64
+ rst = 0;
65
+ load = 0;
66
+ x = $random;
67
+ a = $random;
68
+ expected = x * a;
69
+ #2;
70
+ load = 1;
71
+ rst = 1;
72
+ #2;
73
+ load = 0;
74
+ #2; // No useful bit at the first clock cycle
75
+ #(bits * 2 * 2); // 2 * bits * clock cycle duration
76
+ $display("%h * %h", x, a);
77
+ $display("expected %h, got %h (%s)", expected, y_value, expected==y_value ? "ok " : "err");
78
+ end
79
+ $finish;
80
+ end
81
+ endmodule
82
+
83
+ module sreg #(parameter width = 32) (
84
+ input clk,
85
+ input rst,
86
+ input direction, // 0 -> load from lsb side; 1 -> load from msb side
87
+ input serial_msb,
88
+ input serial_lsb,
89
+ input load,
90
+ input[width-1:0] load_value,
91
+ output[width-1:0] value
92
+ );
93
+ reg[width-1:0] store;
94
+
95
+ assign value = store;
96
+
97
+ always @ (posedge clk or negedge rst) begin
98
+ if (!rst) begin
99
+ store <= {(width){1'b0}};
100
+ end else begin
101
+ store <= load ? load_value :
102
+ direction ? {serial_msb, store[width-1:1]}:
103
+ {store[width-2:0], serial_lsb};
104
+ end
105
+ end
106
+ endmodule
@@ -0,0 +1,286 @@
1
+ // Copyright 2023 Efabless Corporation
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ // (Parameterized) Unsigned Serial/Parallel Multiplier:
16
+ // - Multiplicand x (Input bit-serially)
17
+ // - Multiplier a (All bits at the same time/Parallel)
18
+ // - Product y (Output bit-serial)
19
+
20
+ `default_nettype none
21
+ /*
22
+ *-------------------------------------------------------------
23
+ *
24
+ * user_proj_example
25
+ *
26
+ * This is an example of a (trivially simple) user project,
27
+ * showing how the user project can connect to the logic
28
+ * analyzer, the wishbone bus, and the I/O pads.
29
+ *
30
+ * This project generates an integer count, which is output
31
+ * on the user area GPIO pads (digital output only). The
32
+ * wishbone connection allows the project to be controlled
33
+ * (start and stop) from the management SoC program.
34
+ *
35
+ * See the testbenches in directory "mprj_counter" for the
36
+ * example programs that drive this user project. The three
37
+ * testbenches are "io_ports", "la_test1", and "la_test2".
38
+ *
39
+ *-------------------------------------------------------------
40
+ */
41
+
42
+ module SPM_example #(
43
+ parameter BITS = 32
44
+ )(
45
+ `ifdef USE_POWER_PINS
46
+ inout vccd1, // User area 1 1.8V supply
47
+ inout vssd1, // User area 1 digital ground
48
+ // inout vdda2,
49
+ // inout vssd2,
50
+ `endif
51
+
52
+ // Wishbone Slave ports (WB MI A)
53
+ input wb_clk_i,
54
+ input wb_rst_i,
55
+ input wbs_stb_i,
56
+ input wbs_cyc_i,
57
+ input wbs_we_i,
58
+ input [3:0] wbs_sel_i,
59
+ input [31:0] wbs_dat_i,
60
+ input [31:0] wbs_adr_i,
61
+ output reg wbs_ack_o,
62
+ output reg [31:0] wbs_dat_o,
63
+
64
+ // Logic Analyzer Signals
65
+ input [127:0] la_data_in,
66
+ output [127:0] la_data_out,
67
+ input [127:0] la_oenb,
68
+
69
+ // IOs
70
+ input wire [`MPRJ_IO_PADS-1:0] io_in,
71
+ output wire [`MPRJ_IO_PADS-1:0] io_out,
72
+ output wire [`MPRJ_IO_PADS-1:0] io_oeb,
73
+
74
+ // IRQ
75
+ output [2:0] irq
76
+ );
77
+ wire clk;
78
+ wire rst;
79
+
80
+
81
+ wire [31:0] rdata;
82
+ wire [31:0] wdata;
83
+ wire [BITS-1:0] count;
84
+
85
+ wire valid;
86
+ wire [3:0] wstrb;
87
+ wire [31:0] la_write;
88
+
89
+ //addresses for registers
90
+ localparam X_OFF = 805306368, Y_OFF = 805306372, Y0_OFF = 805306376, Y1_OFF = 805306380, STAT_OFF = 32'h30000010;
91
+ //states of the state machine
92
+ localparam S0 = 0, S1 = 1, S2 = 2, S3 = 3;
93
+ reg [3:0] STATE, nstate;
94
+ reg [7:0] CNT, ncnt;
95
+ //Registers for the multiplicand, multiplier, product
96
+ reg [31:0] A, X;
97
+ reg [63:0] Y0;
98
+ wire status; // status register
99
+ assign status = STATE == S0 ? 1:0; // if status reg == 1 means data is ready to be read or change the existing data
100
+ //wire for the current product bit
101
+ wire y;
102
+ //Registers for the WB bus
103
+ reg [7:0] WB_address;
104
+ reg WB_Read, WB_Write;
105
+
106
+ // WB MI A
107
+ assign valid = wbs_cyc_i && wbs_stb_i;
108
+ assign wstrb = wbs_sel_i & {4{wbs_we_i}};
109
+ //assign wbs_dat_o = rdata;
110
+ assign wdata = wbs_dat_i;
111
+
112
+ // IO
113
+ assign io_out = {(`MPRJ_IO_PADS){1'b0}};
114
+ assign io_oeb = {(`MPRJ_IO_PADS){rst}};
115
+
116
+ // IRQ
117
+ assign irq = 3'b000; // Unused
118
+
119
+ // LA
120
+ assign la_data_out = {(127){1'b0}};
121
+ // Assuming LA probes [63:32] are for controlling the count register
122
+ assign la_write = ~la_oenb[63:32] & ~{BITS{valid}};
123
+ // Assuming LA probes [65:64] are for controlling the count clk & reset
124
+ // assign clk = (~la_oenb[64]) ? la_data_in[64]: wb_clk_i;
125
+ // assign rst = (~la_oenb[65]) ? la_data_in[65]: wb_rst_i;
126
+ assign clk = wb_clk_i;
127
+ assign rst = wb_rst_i;
128
+
129
+ always @(posedge clk or posedge rst) begin //assuming that we have posedge rst
130
+
131
+ if(rst) begin
132
+ A <= 32'b0;
133
+ //wbs_ack_o <= 1'b0;
134
+ end
135
+ else if(valid && wbs_we_i && (wbs_adr_i==X_OFF)) begin
136
+ A <= wbs_dat_i;
137
+ // wbs_dat_o <= A;
138
+ // wbs_ack_o <= 1'b1;
139
+ end
140
+ end
141
+
142
+ always @(posedge clk or posedge rst) begin //assuming that we have posedge rst
143
+ // wbs_ack_o <= 1'b0;
144
+ if(rst) begin
145
+ //wbs_ack_o <= 1'b0;
146
+ X <= 32'b0;
147
+ end
148
+ else if(STATE==S1) X <= X >>1; //shift right for the X since we always take the least significant bit in the multiplication
149
+ else if(valid && wbs_we_i && (wbs_adr_i==Y_OFF)) begin //the reason we have a separate always block for the X is the shift right action
150
+ X <= wbs_dat_i;
151
+ // wbs_dat_o <= X;
152
+ // wbs_ack_o <= 1'b1;
153
+ end
154
+
155
+ end
156
+
157
+ always@(posedge clk) begin //a signal such as wbs_dat_o can be manipulated within one always block only
158
+ if(valid && wbs_we_i && (wbs_adr_i==Y_OFF)) begin
159
+ wbs_dat_o <= X;
160
+ end
161
+ else if(valid && wbs_we_i && (wbs_adr_i==X_OFF)) begin
162
+ wbs_dat_o <= A;
163
+ end
164
+ else if(valid && !wbs_we_i && (wbs_adr_i==Y0_OFF)) begin
165
+ wbs_dat_o <= Y0[31:0];
166
+ // wbs_ack_o <= 1'b1;
167
+ end
168
+ else if(valid && !wbs_we_i && (wbs_adr_i==Y1_OFF)) begin
169
+ wbs_dat_o <= Y0[63:32];
170
+ end
171
+ else if(valid && !wbs_we_i && (wbs_adr_i==STAT_OFF)) begin
172
+ wbs_dat_o <= status;
173
+ end
174
+ end
175
+
176
+ always@(posedge clk) begin
177
+ if(wbs_ack_o) begin
178
+ wbs_ack_o <= 1'b0;
179
+ end
180
+ else if((valid && !wbs_we_i && (wbs_adr_i==Y1_OFF)) || (valid && !wbs_we_i && (wbs_adr_i==Y0_OFF)) || (valid && wbs_we_i && (wbs_adr_i==Y_OFF)) || (valid && wbs_we_i && (wbs_adr_i==X_OFF)) || (valid && !wbs_we_i && (wbs_adr_i==STAT_OFF))) begin
181
+ wbs_ack_o <= 1'b1;
182
+ end
183
+ end
184
+
185
+ always @(posedge clk or posedge rst) begin
186
+ if(rst) begin
187
+ Y0 <= 64'b0;
188
+ end
189
+ else if(STATE==S1)
190
+ Y0 <= {y, Y0[63:1]}; //taking the result from the SPM and shifting it right one bit at a time
191
+
192
+ end
193
+
194
+ always @(posedge clk or posedge rst) begin
195
+ if(rst) begin
196
+ STATE <= S0;
197
+ end
198
+ else
199
+ STATE <=nstate; //moving to the next state each clk cycle or on rst
200
+ end
201
+
202
+ always @(*) begin
203
+ case(STATE)
204
+ S0: if(valid && wbs_we_i && (wbs_adr_i==Y_OFF)) nstate=S1; else nstate=S0;
205
+ S1: if(CNT==64) nstate=S0; else nstate=S1; //state 1 means that both numbers are ready now.
206
+ default: nstate=S0;
207
+ endcase
208
+ end
209
+
210
+ always @(posedge clk or posedge rst) begin
211
+ if(rst) begin
212
+ CNT <= 8'b0;
213
+ end
214
+ else
215
+ CNT <= ncnt;
216
+ end
217
+
218
+ always @(*) begin
219
+ ncnt = 0;
220
+ if(CNT==64) ncnt <=0;
221
+ else if(STATE==S1) ncnt = CNT + 1;
222
+ end
223
+ spm spm(.clk(clk), .rst(!rst), .a(A), .x(X[0]), .y(y));
224
+
225
+
226
+ endmodule
227
+
228
+ // (Parameterized) Unsigned Serial/Parallel Multiplier:
229
+ // - Multiplicand x (Input bit-serially)
230
+ // - Multiplier a (All bits at the same time/Parallel)
231
+ // - Product y (Output bit-serial)
232
+ module spm #(parameter bits=32) (
233
+ input clk,
234
+ input rst,
235
+ input x,
236
+ input[bits-1: 0] a,
237
+ output y
238
+ );
239
+ wire[bits: 0] y_chain;
240
+ assign y_chain[0] = 0;
241
+ assign y = y_chain[bits];
242
+
243
+ wire[bits-1:0] a_flip;
244
+ genvar i;
245
+ generate
246
+ for (i = 0; i < bits; i = i + 1) begin : flip_block
247
+ assign a_flip[i] = a[bits - i - 1];
248
+ end
249
+ endgenerate
250
+
251
+ delayed_serial_adder dsa[bits-1:0](
252
+ .clk(clk),
253
+ .rst(rst),
254
+ .x(x),
255
+ .a(a_flip),
256
+ .y_in(y_chain[bits-1:0]),
257
+ .y_out(y_chain[bits:1])
258
+ );
259
+
260
+ endmodule
261
+
262
+ module delayed_serial_adder(
263
+ input clk,
264
+ input rst,
265
+ input x,
266
+ input a,
267
+ input y_in,
268
+ output reg y_out
269
+ );
270
+ reg last_carry;
271
+ wire last_carry_next;
272
+ wire y_out_next;
273
+
274
+ wire g = x & a;
275
+ assign {last_carry_next, y_out_next} = g + y_in + last_carry;
276
+
277
+ always @ (posedge clk or negedge rst) begin
278
+ if (!rst) begin
279
+ last_carry <= 1'b0;
280
+ y_out <= 1'b0;
281
+ end else begin
282
+ last_carry <= last_carry_next;
283
+ y_out <= y_out_next;
284
+ end
285
+ end
286
+ endmodule