Skip to content

Commit d03b6e6

Browse files
Add Colonnade digital CiM architecture + some CiM comment updates
1 parent 9656329 commit d03b6e6

7 files changed

Lines changed: 1275 additions & 28 deletions

File tree

examples/arches/compute_in_memory/basic_analog.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,16 @@ arch:
2626
signed_sum_across_weights: False
2727

2828
# Architecture & CiM Array Structure ----------------------------------------------
29+
# DEFINITIONS:
30+
# - Cell: Smallest structure capable of storing memory. Note that a cell may store
31+
# more than one bit. For example, a cell consisting of a RRAM device may store >1
32+
# bits, while a cell consisting of an SRAM bitcell may store only 1 bit.
33+
# - CiM Unit: Smallest structure capable of computing an analog MAC
34+
# - CiM Unit Width Cells: Number of CiM unit cells that are accessed as one. These
35+
# cells receive one analog input and compute one analog MAC per timestep.
36+
# - CiM Unit Depth Cells: Number of independent groups of "CiM Unit Width" cells
37+
# that form a CiM unit. Each of these groups is indepently addressible and
38+
# operates in must be activated in a different timestep than the others.
2939
cim_unit_width_cells: 1
3040
cim_unit_depth_cells: 1
3141
bits_per_cell: 8
Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
# @ARTICLE{9373949,
2+
# author={Kim, Hyunjoon and Yoo, Taegeun and Kim, Tony Tae-Hyoung and Kim, Bongjin},
3+
# journal={IEEE Journal of Solid-State Circuits},
4+
# title={Colonnade: A Reconfigurable SRAM-Based Digital Bit-Serial Compute-In-Memory Macro for Processing Neural Networks},
5+
# year={2021},
6+
# volume={56},
7+
# number={7},
8+
# pages={2221-2233},
9+
# doi={10.1109/JSSC.2021.3061508}}
10+
11+
{{include_text('_include.yaml')}}
12+
{{add_to_path('./memory_cells')}}
13+
14+
arch:
15+
# ===================================================================================
16+
# Architecture-specific variables.
17+
# ===================================================================================
18+
variables:
19+
# Inherit these from _include.yaml. Many definitions are included there.
20+
<<: *variables_global
21+
22+
# Encoding-dependent parameters ---------------------------------------------------
23+
encoded_input_bits: input_bits
24+
encoded_weight_bits: weight_bits + ceil(log2(array_parallel_inputs))
25+
encoded_output_bits: output_bits
26+
27+
input_encoding_func: offset_encode_hist
28+
weight_encoding_func: offset_encode_hist
29+
30+
# For accuracy model. Can in-array accumulation include signed values? Signed
31+
# accumulation not compatible with offset encoding (since offset encoding makes
32+
# values non-negative)
33+
signed_sum_across_inputs: False
34+
signed_sum_across_weights: False
35+
36+
# Architecture & CiM Array Structure ----------------------------------------------
37+
# DEFINITIONS:
38+
# - Cell: Smallest structure capable of storing memory. Note that a cell may store
39+
# more than one bit. For example, a cell consisting of a RRAM device may store >1
40+
# bits, while a cell consisting of an SRAM bitcell may store only 1 bit.
41+
# - CiM Unit: Smallest structure capable of computing an analog MAC
42+
# - CiM Unit Width Cells: Number of CiM unit cells that are accessed as one. These
43+
# cells receive one analog input and compute one analog MAC per timestep.
44+
# - CiM Unit Depth Cells: Number of independent groups of "CiM Unit Width" cells
45+
# that form a CiM unit. Each of these groups is indepently addressible and
46+
# operates in must be activated in a different timestep than the others.
47+
cim_unit_width_cells: 1
48+
cim_unit_depth_cells: 1
49+
bits_per_cell: 1
50+
51+
# Data Converters -----------------------------------------------------------------
52+
adc_resolution: 1
53+
voltage_dac_resolution: 1
54+
temporal_dac_resolution: 1
55+
n_adc_per_bank: 1
56+
57+
# Hardware ------------------------------------------------------------------------
58+
cycle_period: base_latency * voltage_latency_scale * latency_pipeline_scale
59+
read_pulse_width: cycle_period
60+
61+
n_regs_per_col: 16
62+
n_rows_per_reg: 8
63+
64+
# True = 100 MHz fixed clock for energy tests, False = variable frequency
65+
# based on critical path
66+
force_100mhz: False
67+
bit_pipelined: True
68+
n_adders_critical_path: encoded_weight_bits + n_rows_per_reg + 2
69+
critical_path_latency: n_adders_critical_path * 0.4e-9
70+
71+
base_latency: 10e-9 if force_100mhz else critical_path_latency
72+
latency_pipeline_scale: 1 if bit_pipelined else (n_regs_per_col + 1)
73+
74+
extra_attributes_for_all_component_models:
75+
<<: *cim_component_attributes
76+
tech_node: tech_node
77+
cycle_period: cycle_period
78+
79+
# ===================================================================================
80+
# Architecture
81+
# ===================================================================================
82+
nodes:
83+
# This memory catches sliding windows that may be sent spatially in the array. E.g.,
84+
# convolution steps spatially unrolled onto columns with overlapping windows.
85+
- !Memory
86+
name: DummyRowDriverMemory
87+
component_class: Dummy
88+
# Size = one input value per row (max number of inputs we can do in parallel)
89+
size: input.bits_per_value * array_parallel_inputs
90+
# no_resend_to_below prevents reuse across temporal iterations because this isn't
91+
# really a memory.
92+
tensors: {keep: input, no_resend_to_below: input}
93+
94+
# Row drivers feed inputs onto the rows of the array.
95+
- !Toll
96+
name: RowDrivers
97+
<<: [*input_sliced, *one_action_per_value]
98+
tensors: {keep: input}
99+
direction: down
100+
component_class: ArrayRowDrivers
101+
area_scale: row_col_drivers_area_scale
102+
103+
# The input ports of the CiM logic are modeled here, representing the energy to drive
104+
# all of the adders that will be switching for each input bit. We put this logic up
105+
# here, not by the CiM unit, because the input bits fan out to all columns regardless
106+
# of if the columns are used, so we charge the full energy here for each input bit
107+
# entering the array.
108+
- !Toll
109+
name: DigitalLogicInputPorts
110+
<<: [*input_sliced, *one_action_per_value]
111+
tensors: {keep: input}
112+
direction: down
113+
component_class: ColonnadeCimLogicInputPort
114+
extra_attributes_for_component_model:
115+
n_instances: array_bitlines
116+
switching_activity: (average_input_value * (1 - average_input_value)) ** 0.5
117+
voltage: voltage
118+
voltage_energy_scale: voltage_energy_scale
119+
120+
# A bitline decoder is used to select array columns.
121+
- !Toll
122+
name: ColumnDrivers
123+
<<: [*both_sliced, *one_action_per_value]
124+
tensors: {keep: output}
125+
direction: up
126+
component_class: ArrayColumnDrivers
127+
area_scale: row_col_drivers_area_scale
128+
# Cols active at once = 1 to create a full decoder. We use 1 /
129+
# array_parallel_outputs scaling because we actually can accumulate outputs in
130+
# parallel.
131+
latency_scale: 1 / array_parallel_outputs
132+
extra_attributes_for_component_model: {cols_active_at_once: 1}
133+
134+
# Weight drivers write weights.
135+
- !Toll
136+
name: WeightDrivers
137+
tensors: {keep: weight & Above}
138+
direction: down
139+
component_class: ArrayRowDrivers
140+
bits_per_action: average_weight_bits_per_slice
141+
area_scale: row_col_drivers_area_scale
142+
extra_attributes_for_component_model: {<<: *weight_drivers_attributes}
143+
144+
# Each column stores a different weight slices. Columns share inputs.
145+
- !Container
146+
name: Column
147+
spatial:
148+
# ARRAY_COLUMNS suffix used for used for counting the array size
149+
- name: column_ARRAY_COLUMNS
150+
fanout: 128
151+
# Note: may_reuse here and not reuse because we may have columns that reuse some,
152+
# but not all, input values, so we want reuse to be optional and only for inputs.
153+
may_reuse: input
154+
min_usage: 1
155+
usage_scale: n_weight_slices
156+
157+
# Column bandwidth limiter to limit write speed (only one value can be written per
158+
# column per cycle)
159+
- !Toll
160+
name: ColumnBandwidthLimiter
161+
tensors: {keep: (weight | output) & Above}
162+
direction: {Outputs: up, ~Outputs: down}
163+
component_class: Dummy
164+
bits_per_value:
165+
weight: 1
166+
output: n_input_slices
167+
actions: [{name: read, latency: cycle_period}]
168+
169+
# Each group of rows has a register for pipelining. Rows share outputs.
170+
- !Container
171+
name: RowGroup
172+
spatial:
173+
- name: group_ARRAY_ROWS
174+
fanout: n_regs_per_col
175+
reuse: output
176+
min_usage: 1
177+
178+
# Register stores partially-accumulated outputs. They are used for pipelining the
179+
# design to run the array at a higher clock frequency.
180+
- !Toll
181+
name: Register
182+
<<: [*both_sliced, *one_action_per_value]
183+
tensors: {keep: output}
184+
direction: up
185+
component_class: ColonnadeRegister
186+
extra_attributes_for_component_model:
187+
width: encoded_output_bits
188+
voltage_energy_scale: voltage_energy_scale
189+
190+
# Each row receives a different input slice. Rows share outputs.
191+
- !Container
192+
name: Row
193+
spatial:
194+
# ARRAY_ROWS suffix used for used for counting the array size
195+
- name: row_ARRAY_ROWS
196+
fanout: n_rows_per_reg
197+
reuse: output
198+
min_usage: 1
199+
200+
# CiM units stores weights and computes MACs. Each CiM unit stores up to
201+
# cim_unit_depth_cells indepedently-addressable weight slices, with up to
202+
# cim_unit_width_cells * cim_unit_depth_cells in a weight slice. Only one weight slice
203+
# can be used at a time.
204+
- !Memory
205+
name: CimUnit
206+
# Computes with one input slice * weight slice at a time. Computations are
207+
# parallelized across weight slices, and input slices are processed sequentially.
208+
<<: [*both_sliced_weight_slices_parallelized, *one_action_per_value]
209+
tensors:
210+
keep: weight
211+
# Write weights at most once
212+
no_refetch_from_above: weight
213+
# Can store values at this level longer than levels above, which lets the mapping
214+
# be maximally-weight-stationary (CimUnit weight storage node as high as
215+
# possible).
216+
force_memory_hierarchy_order: False
217+
# Each instance of this component represents n_weight_slices weight slices, meaning
218+
# that it holds a full weight
219+
size: cim_unit_width_cells * cim_unit_depth_cells * bits_per_cell
220+
component_class: MemoryCell
221+
# CimUnits represent cim_unit_width_cells * cim_unit_depth_cells memory cells tied
222+
# together into one weight
223+
extra_attributes_for_component_model:
224+
n_instances: cim_unit_width_cells * cim_unit_depth_cells
225+
226+
# CiM logic (adder switching) performs MACs in the memory array. In Colonnade they
227+
# include a XOR gate to perform the multiply and an adder that sums values from this
228+
# XOR gate, the previous row, and the carry from the previous column.
229+
- !Toll
230+
name: CimLogic
231+
<<: [*both_sliced_weight_slices_parallelized, *one_action_per_value]
232+
tensors: {keep: weight}
233+
direction: down
234+
component_class: ColonnadeCimLogic
235+
extra_attributes_for_component_model:
236+
width: cim_unit_width_cells * bits_per_cell
237+
p_switch: (average_input_value * (1 - average_input_value)) ** 0.5
238+
switching_activity: n_adders_critical_path * p_switch
239+
voltage_energy_scale: voltage_energy_scale
240+
241+
# We account for compute energy and latency in other components, so just use a dummy
242+
# compute here.
243+
- !Compute
244+
name: FreeCompute
245+
component_class: Dummy
246+
enabled: len(All) == 3
247+
248+
249+
# These variables pertain to the workload, microarch, and circuits. They should be
250+
# matched between architectures when comparing for a fair comparison.
251+
variables:
252+
inputs_hist: [1, 1, 1, 1, 1, 1, 1]
253+
weights_hist: [1, 1, 1, 1, 1, 1, 1]
254+
outputs_hist: inputs_hist
255+
256+
## Microarch ------------------------------------------------------------------------
257+
supported_input_bits: 16
258+
supported_weight_bits: 16
259+
supported_output_bits: 24
260+
min_supported_input_bits: 1
261+
min_supported_weight_bits: 1
262+
min_supported_output_bits: 1
263+
264+
# Circuits --------------------------------------------------------------------------
265+
voltage: 0.8
266+
tech_node: 65e-9 # 65nm
267+
cell_config: "{{find_path('sram_colonnade_jssc_2021.yaml')}}"
268+
voltage_energy_scale: (voltage / 0.8) ** 2
269+
voltage_latency_scale: 0.8 / voltage
270+
271+
# Calibration -----------------------------------------------------------------------
272+
adc_energy_scale: 1 * voltage_energy_scale
273+
adc_area_scale: 1
274+
row_col_drivers_area_scale: 1
275+
276+
277+
# =====================================================================================
278+
# Default Workload
279+
# =====================================================================================
280+
# This workload is sized to get peak throughput & energy efficiency.
281+
# 128 columns × (16 regs × 8 rows/reg) = 128 × 128 rows
282+
workload:
283+
rank_sizes:
284+
M: 1
285+
N: 128
286+
K: 128
287+
288+
einsums:
289+
- name: Matmul
290+
tensor_accesses:
291+
- {name: input, projection: [m, k], bits_per_value: 1}
292+
- {name: weight, projection: [k, n], bits_per_value: 1}
293+
- {name: output, projection: [m, n], output: True, bits_per_value: 1}
294+
295+
renames: {}

0 commit comments

Comments
 (0)