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.
- librelane/__init__.py +38 -0
- librelane/__main__.py +479 -0
- librelane/__version__.py +43 -0
- librelane/common/__init__.py +63 -0
- librelane/common/cli.py +75 -0
- librelane/common/drc.py +246 -0
- librelane/common/generic_dict.py +319 -0
- librelane/common/metrics/__init__.py +35 -0
- librelane/common/metrics/__main__.py +413 -0
- librelane/common/metrics/library.py +354 -0
- librelane/common/metrics/metric.py +186 -0
- librelane/common/metrics/util.py +279 -0
- librelane/common/misc.py +456 -0
- librelane/common/ring_buffer.py +63 -0
- librelane/common/tcl.py +80 -0
- librelane/common/toolbox.py +549 -0
- librelane/common/tpe.py +41 -0
- librelane/common/types.py +116 -0
- librelane/config/__init__.py +32 -0
- librelane/config/__main__.py +155 -0
- librelane/config/config.py +1025 -0
- librelane/config/flow.py +490 -0
- librelane/config/pdk_compat.py +255 -0
- librelane/config/preprocessor.py +464 -0
- librelane/config/removals.py +45 -0
- librelane/config/variable.py +743 -0
- librelane/container.py +285 -0
- librelane/env_info.py +320 -0
- librelane/examples/spm/config.yaml +33 -0
- librelane/examples/spm/pin_order.cfg +14 -0
- librelane/examples/spm/src/impl.sdc +73 -0
- librelane/examples/spm/src/signoff.sdc +68 -0
- librelane/examples/spm/src/spm.v +73 -0
- librelane/examples/spm/verify/spm_tb.v +106 -0
- librelane/examples/spm-user_project_wrapper/SPM_example.v +286 -0
- librelane/examples/spm-user_project_wrapper/base_sdc_file.sdc +145 -0
- librelane/examples/spm-user_project_wrapper/config-tut.json +12 -0
- librelane/examples/spm-user_project_wrapper/config.json +13 -0
- librelane/examples/spm-user_project_wrapper/defines.v +66 -0
- librelane/examples/spm-user_project_wrapper/template.def +7656 -0
- librelane/examples/spm-user_project_wrapper/user_project_wrapper.v +123 -0
- librelane/flows/__init__.py +24 -0
- librelane/flows/builtins.py +18 -0
- librelane/flows/classic.py +327 -0
- librelane/flows/cli.py +463 -0
- librelane/flows/flow.py +1049 -0
- librelane/flows/misc.py +71 -0
- librelane/flows/optimizing.py +179 -0
- librelane/flows/sequential.py +367 -0
- librelane/flows/synth_explore.py +173 -0
- librelane/help/__main__.py +39 -0
- librelane/logging/__init__.py +40 -0
- librelane/logging/logger.py +323 -0
- librelane/open_pdks_rev +1 -0
- librelane/plugins.py +21 -0
- librelane/py.typed +0 -0
- librelane/scripts/base.sdc +80 -0
- librelane/scripts/klayout/Readme.md +2 -0
- librelane/scripts/klayout/open_design.py +63 -0
- librelane/scripts/klayout/render.py +121 -0
- librelane/scripts/klayout/stream_out.py +176 -0
- librelane/scripts/klayout/xml_drc_report_to_json.py +45 -0
- librelane/scripts/klayout/xor.drc +120 -0
- librelane/scripts/magic/Readme.md +1 -0
- librelane/scripts/magic/common/read.tcl +114 -0
- librelane/scripts/magic/def/antenna_check.tcl +35 -0
- librelane/scripts/magic/def/mag.tcl +19 -0
- librelane/scripts/magic/def/mag_gds.tcl +79 -0
- librelane/scripts/magic/drc.tcl +78 -0
- librelane/scripts/magic/extract_spice.tcl +98 -0
- librelane/scripts/magic/gds/drc_batch.tcl +74 -0
- librelane/scripts/magic/gds/erase_box.tcl +32 -0
- librelane/scripts/magic/gds/extras_mag.tcl +45 -0
- librelane/scripts/magic/gds/mag_with_pointers.tcl +31 -0
- librelane/scripts/magic/get_bbox.tcl +11 -0
- librelane/scripts/magic/lef/extras_maglef.tcl +61 -0
- librelane/scripts/magic/lef/maglef.tcl +26 -0
- librelane/scripts/magic/lef.tcl +57 -0
- librelane/scripts/magic/open.tcl +28 -0
- librelane/scripts/magic/wrapper.tcl +21 -0
- librelane/scripts/netgen/setup.tcl +28 -0
- librelane/scripts/odbpy/apply_def_template.py +49 -0
- librelane/scripts/odbpy/cell_frequency.py +107 -0
- librelane/scripts/odbpy/check_antenna_properties.py +116 -0
- librelane/scripts/odbpy/contextualize.py +109 -0
- librelane/scripts/odbpy/defutil.py +573 -0
- librelane/scripts/odbpy/diodes.py +373 -0
- librelane/scripts/odbpy/disconnected_pins.py +305 -0
- librelane/scripts/odbpy/eco_buffer.py +181 -0
- librelane/scripts/odbpy/eco_diode.py +139 -0
- librelane/scripts/odbpy/filter_unannotated.py +100 -0
- librelane/scripts/odbpy/io_place.py +482 -0
- librelane/scripts/odbpy/ioplace_parser/__init__.py +23 -0
- librelane/scripts/odbpy/ioplace_parser/parse.py +147 -0
- librelane/scripts/odbpy/label_macro_pins.py +277 -0
- librelane/scripts/odbpy/lefutil.py +97 -0
- librelane/scripts/odbpy/placers.py +162 -0
- librelane/scripts/odbpy/power_utils.py +397 -0
- librelane/scripts/odbpy/random_place.py +57 -0
- librelane/scripts/odbpy/reader.py +250 -0
- librelane/scripts/odbpy/remove_buffers.py +173 -0
- librelane/scripts/odbpy/snap_to_grid.py +57 -0
- librelane/scripts/odbpy/wire_lengths.py +93 -0
- librelane/scripts/openroad/antenna_check.tcl +20 -0
- librelane/scripts/openroad/antenna_repair.tcl +31 -0
- librelane/scripts/openroad/basic_mp.tcl +24 -0
- librelane/scripts/openroad/buffer_list.tcl +10 -0
- librelane/scripts/openroad/common/dpl.tcl +24 -0
- librelane/scripts/openroad/common/dpl_cell_pad.tcl +26 -0
- librelane/scripts/openroad/common/grt.tcl +32 -0
- librelane/scripts/openroad/common/io.tcl +540 -0
- librelane/scripts/openroad/common/pdn_cfg.tcl +135 -0
- librelane/scripts/openroad/common/resizer.tcl +103 -0
- librelane/scripts/openroad/common/set_global_connections.tcl +78 -0
- librelane/scripts/openroad/common/set_layer_adjustments.tcl +31 -0
- librelane/scripts/openroad/common/set_power_nets.tcl +30 -0
- librelane/scripts/openroad/common/set_rc.tcl +75 -0
- librelane/scripts/openroad/common/set_routing_layers.tcl +30 -0
- librelane/scripts/openroad/cts.tcl +80 -0
- librelane/scripts/openroad/cut_rows.tcl +24 -0
- librelane/scripts/openroad/dpl.tcl +24 -0
- librelane/scripts/openroad/drt.tcl +37 -0
- librelane/scripts/openroad/fill.tcl +30 -0
- librelane/scripts/openroad/floorplan.tcl +145 -0
- librelane/scripts/openroad/gpl.tcl +88 -0
- librelane/scripts/openroad/grt.tcl +30 -0
- librelane/scripts/openroad/gui.tcl +37 -0
- librelane/scripts/openroad/insert_buffer.tcl +127 -0
- librelane/scripts/openroad/ioplacer.tcl +67 -0
- librelane/scripts/openroad/irdrop.tcl +51 -0
- librelane/scripts/openroad/pdn.tcl +52 -0
- librelane/scripts/openroad/rcx.tcl +32 -0
- librelane/scripts/openroad/repair_design.tcl +70 -0
- librelane/scripts/openroad/repair_design_postgrt.tcl +48 -0
- librelane/scripts/openroad/rsz_timing_postcts.tcl +68 -0
- librelane/scripts/openroad/rsz_timing_postgrt.tcl +70 -0
- librelane/scripts/openroad/sta/check_macro_instances.tcl +53 -0
- librelane/scripts/openroad/sta/corner.tcl +393 -0
- librelane/scripts/openroad/tapcell.tcl +25 -0
- librelane/scripts/openroad/write_views.tcl +27 -0
- librelane/scripts/pyosys/construct_abc_script.py +177 -0
- librelane/scripts/pyosys/json_header.py +84 -0
- librelane/scripts/pyosys/synthesize.py +493 -0
- librelane/scripts/pyosys/ys_common.py +153 -0
- librelane/scripts/tclsh/hello.tcl +1 -0
- librelane/state/__init__.py +24 -0
- librelane/state/__main__.py +61 -0
- librelane/state/design_format.py +195 -0
- librelane/state/state.py +359 -0
- librelane/steps/__init__.py +61 -0
- librelane/steps/__main__.py +510 -0
- librelane/steps/checker.py +637 -0
- librelane/steps/common_variables.py +340 -0
- librelane/steps/cvc_rv.py +169 -0
- librelane/steps/klayout.py +509 -0
- librelane/steps/magic.py +576 -0
- librelane/steps/misc.py +160 -0
- librelane/steps/netgen.py +253 -0
- librelane/steps/odb.py +1088 -0
- librelane/steps/openroad.py +2460 -0
- librelane/steps/openroad_alerts.py +102 -0
- librelane/steps/pyosys.py +640 -0
- librelane/steps/step.py +1571 -0
- librelane/steps/tclstep.py +288 -0
- librelane/steps/verilator.py +222 -0
- librelane/steps/yosys.py +371 -0
- librelane-2.4.0.dist-info/METADATA +169 -0
- librelane-2.4.0.dist-info/RECORD +170 -0
- librelane-2.4.0.dist-info/WHEEL +4 -0
- 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
|