-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathmain_controller.py
More file actions
176 lines (150 loc) · 7.33 KB
/
Copy pathmain_controller.py
File metadata and controls
176 lines (150 loc) · 7.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
'''
Author : Pavia Bera - University of South Florida
This is a simulator for Domain wall memory (DWM)
DWM leverages the 'shift-register' nature of spintronic domain-wall memory (DWM).
Shift-based scheme utilizes a multi-nanowire approach to ensure that reads and writes
can be more effectively aligned with access ports for simultaneous access in the same cycle.
'''
import numpy as np
import WriteData as adt
import LogicOperation as logicop
import ArithmaticOperation as ao
from fault_modeling import f_percent_model
import config as config
class DBC:
TRd_size = config.TRd_size
bit_length = config.bit_length
memory_size = config.memory_size
fault_mode = config.fault_mode
Local_row_buffer = [0] * bit_length
def __init__(self):
self.bit_length = DBC.bit_length - 1
self.memory_size = DBC.memory_size
self.TRd_head = 0
self.TRd_tail = self.TRd_head + DBC.TRd_size - 1
self.memory = [["0" for _ in range(self.bit_length + 1)] for _ in range(self.memory_size)]
self.base_param = {k: 0 for k in ['write', 'TR_writes', 'read', 'TR_reads', 'shift', 'STORE']}
# quick dispatch tables
self.logic_ops = {
'AND': logicop.And, 'NAND': logicop.Nand, 'XOR': logicop.Xor,
'XNOR': logicop.Xnor, 'OR': logicop.Or, 'NOR': logicop.Nor, 'NOT': logicop.Not
}
self.arith_ops = {'ADD': ao.addition, 'MULT': ao.multiply}
# ---------------------------------------------------------------------
# Helper utilities
# ---------------------------------------------------------------------
def reset_param(self):
return self.base_param.copy()
def move_track(self, move_by: int, use_tail: bool):
"""Shift TRd head/tail pointer and accumulate shift."""
if use_tail:
self.TRd_tail += move_by
self.TRd_head = self.TRd_tail - DBC.TRd_size + 1
else:
self.TRd_head += move_by
self.TRd_tail = self.TRd_head + DBC.TRd_size - 1
return abs(move_by)
@staticmethod
def format_instruction(instr, ap):
"""Attach access port suffix/prefix."""
if instr == 'overwrite': return f'W {ap}'
if isinstance(instr, int): return str(instr)
if instr == 'Read': return f'R {ap}'
if instr in ('CARRY', 'CARRYPRIME'): return f'{instr}_{ap}'
if 'SHL' in instr or 'SHR' in instr: return f'{instr} {ap}'
return instr
@staticmethod
def hex_to_bin(hex_str, length=None):
val = bin(int(hex_str, 16))[2:]
if length: val = val.zfill(length)
return list(val)
@staticmethod
def bin_to_hex(bin_list):
s = ''.join(map(str, bin_list))
return hex(int(s, 2))[2:]
# ---------------------------------------------------------------------
# Access port resolver
# ---------------------------------------------------------------------
def resolve_access_port(self, row_number):
"""Determine AP0 or AP1 and shift amount."""
if abs(self.TRd_head - row_number) < abs(self.TRd_tail - row_number):
ap, diff, use_tail = 'AP0', row_number - self.TRd_head, False
else:
ap, diff, use_tail = 'AP1', row_number - self.TRd_tail, True
shift_amt = self.move_track(diff, use_tail)
return ap, shift_amt
# ---------------------------------------------------------------------
# Core controller logic
# ---------------------------------------------------------------------
def controller(self, row_number, instruction, start, end, data_hex=None):
perform_param = self.reset_param()
row_number = int(row_number)
ap, shift_amt = self.resolve_access_port(row_number)
perform_param['shift'] += shift_amt
instruction = self.format_instruction(instruction, ap)
# preload data if given
if data_hex:
DBC.Local_row_buffer = self.hex_to_bin(data_hex, len(data_hex) * 4)
# -----------------------------------------------------------------
# WRITE / READ operations
# -----------------------------------------------------------------
if instruction in ('W AP0', 'W AP1'):
func = adt.overwrite_zero if 'AP0' in instruction else adt.overwrite_one
func(self.memory, self.TRd_head if 'AP0' in instruction else self.TRd_tail, start, end, DBC.Local_row_buffer)
perform_param['write'] = config.bit_length
perform_param['shift'] = config.bit_length - 1
return perform_param
if instruction in ('R AP0', 'R AP1'):
ptr = self.TRd_head if 'AP0' in instruction else self.TRd_tail
buf = [self.memory[ptr][i] for i in range(start, end)]
perform_param['read'] += 1
return perform_param, '0x' + self.bin_to_hex(buf)
# -----------------------------------------------------------------
# SHIFT operations (SHL/SHR)
# -----------------------------------------------------------------
if 'SHL' in instruction or 'SHR' in instruction:
cmd, n, ap = instruction.split()
n = int(n)
ptr = self.TRd_head if ap == 'AP0' else self.TRd_tail
buf = self.memory[ptr]
if cmd == 'SHL':
shifted = buf[n:] + ['0'] * n
else:
shifted = ['0'] * n + buf[:-n]
DBC.Local_row_buffer = shifted
perform_param['read'] += 1
return perform_param, '0x' + self.bin_to_hex(shifted[start:end])
# -----------------------------------------------------------------
# LOGIC operations
# -----------------------------------------------------------------
if instruction in self.logic_ops:
func = self.logic_ops[instruction]
buf = func(self.memory, self.TRd_head, start, end)
if DBC.fault_mode:
f_percent_model(self.memory, self.TRd_head, start, end)
perform_param['TR_reads'] += 1
return perform_param, buf
# -----------------------------------------------------------------
# ARITHMETIC operations
# -----------------------------------------------------------------
if instruction in self.arith_ops:
func = self.arith_ops[instruction]
buf = func(self.memory, self.TRd_head, start, end)
if instruction == 'ADD':
perform_param.update({'write': 15, 'TR_reads': 8})
elif instruction == 'MULT':
perform_param.update({'write': 27, 'TR_writes': 6, 'read': 15, 'TR_reads': 11, 'shift': 17})
return perform_param, buf
# -----------------------------------------------------------------
# CARRY / CARRYPRIME operations
# -----------------------------------------------------------------
if instruction.startswith('CARRY'):
func = logicop.carry_prime if 'PRIME' in instruction else logicop.carry
ptr = self.TRd_head if 'AP0' in instruction else self.TRd_tail
buf = func(self.memory, ptr, start, end)
perform_param['TR_reads'] += 1
return perform_param, buf
# -----------------------------------------------------------------
# Unsupported or unused instructions
# -----------------------------------------------------------------
return perform_param, None