Skip to content

Instantly share code, notes, and snippets.

@uwezi
Last active October 18, 2024 19:38
Show Gist options
  • Save uwezi/d5a565400b7e2f4af624de1a06c4b554 to your computer and use it in GitHub Desktop.
Save uwezi/d5a565400b7e2f4af624de1a06c4b554 to your computer and use it in GitHub Desktop.
[Computer] Animated sequence of a computer adding two numbers. #manim #svg #animate
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
import os, sys
from manim import *
myTexTemplate = TexTemplate()
myTexTemplate.add_to_preamble(r"\usepackage{siunitx}")
MathTex.set_default(tex_template=myTexTemplate)
Tex.set_default(tex_template=myTexTemplate)
config.max_files_cached = 10000
def mkVGroup(mainVMobject, indices):
grp = VGroup()
for i in indices:
grp.add(mainVMobject[i].copy())
return grp
def mkPath(points):
path = VMobject()
path.set_points_as_corners(points)
return path
class computer_en(Scene):
def construct(self):
copyleft = Text(r"© 2023 Uwe Zimmermann",font_size=22).move_to(6.9*LEFT+3.9*DOWN,DL).set_color(WHITE)
self.add(copyleft)
max_t = 15
charge_t = 2
def UCfunc(t):
return (1-np.exp(-t/0.4)) if t < charge_t else np.exp(-(t-charge_t)/2)
self.t = 0
self.run = False
self.UC = 1
self.I1 = 1
self.I2 = 1
def backgroundTimer(dt):
if self.run:
self.t += dt
self.t %= max_t
self.UC = UCfunc(self.t)
self.I1 = 1 - UCfunc(self.t) if self.t < charge_t else 0
self.I2 = UCfunc(self.t)
self.add_updater(backgroundTimer)
circuit = SVGMobject(r"bilder\20231006_computer_02.svg",
stroke_color=WHITE, stroke_width=2, fill_color=WHITE, width=8)
comp = {}
arrow = {}
comp['memory'] = mkVGroup(circuit, [4]).set_color(WHITE)
comp['memory']+= Tex(r"Memory", font_size=24).next_to(comp["memory"],UP,aligned_edge=RIGHT,buff=0.05)
comp['pcnt'] = mkVGroup(circuit, [3]).set_color(WHITE)
comp['pcnt']+= Tex(r"address counter", font_size=24).next_to(comp["pcnt"],DOWN,aligned_edge=LEFT,buff=0.05)
comp['regA'] = mkVGroup(circuit, [0]).set_color(WHITE)
comp['regA']+= Tex(r"register A", font_size=24).next_to(comp["regA"],UP,aligned_edge=RIGHT,buff=0.05)
comp['regB'] = mkVGroup(circuit, [1]).set_color(WHITE)
comp['regB']+= Tex(r"register B", font_size=24).next_to(comp["regB"],UP,aligned_edge=RIGHT,buff=0.05)
comp['ALU'] = mkVGroup(circuit, [5]).set_color(WHITE)
comp['ALU']+= Tex(r"ALU", font_size=24).next_to(comp["ALU"],UP,aligned_edge=LEFT,buff=0.05)
comp['control'] = mkVGroup(circuit, [20]).set_color(WHITE)
comp['control']+= Tex(r"control unit", font_size=24).next_to(comp["control"],UP,aligned_edge=LEFT,buff=0.05)
comp['instruction'] = mkVGroup(circuit, [2]).set_color(WHITE)
comp['instruction']+= Tex(r"instruction", font_size=24).next_to(comp["instruction"],UP, aligned_edge=RIGHT,buff=0.05)
comp['databus'] = mkVGroup(circuit, [11]).set_color(WHITE).set_stroke(width=8)
comp['adrbus'] = mkVGroup(circuit, [40,41]).set_color(WHITE)
comp['result-data'] = mkVGroup(circuit, [53,54,55,19]).set_color(WHITE)
comp['data-A'] = mkVGroup(circuit, [8,14]).set_color(WHITE)
comp['data-B'] = mkVGroup(circuit, [9,13]).set_color(WHITE)
comp['data-instr'] = mkVGroup(circuit, [10,12]).set_color(WHITE)
comp['instr-ctrl'] = mkVGroup(circuit, [49,50]).set_color(WHITE)
comp['ctrl-instr'] = mkVGroup(circuit, [51,52]).set_color(WHITE)
comp['ctrl-regA'] = mkVGroup(circuit, [42,43,44]).set_color(WHITE)
comp['ctrl-regB'] = mkVGroup(circuit, [45,46]).set_color(WHITE)
comp['ctrl-pcnt'] = mkVGroup(circuit, [21]).set_color(WHITE)
comp['instr-ALU'] = mkVGroup(circuit, [47,48]).set_color(WHITE)
comp['data-mem'] = mkVGroup(circuit, [6,16]).set_color(WHITE)
circuit[7].reverse_direction()
comp['data-pcnt'] = mkVGroup(circuit, [7,15]).set_color(WHITE)
comp['regA-ALU'] = mkVGroup(circuit, [17]).set_color(WHITE)
comp['regB-ALU'] = mkVGroup(circuit, [18]).set_color(WHITE)
arrow['result-data_out'] = mkVGroup(circuit, [33]).set_color(WHITE)
arrow['adr-mem_in'] = mkVGroup(circuit, [22]).set_color(WHITE)
arrow['data-A_in'] = mkVGroup(circuit, [24]).set_color(WHITE)
arrow['data-A_out'] = mkVGroup(circuit, [30]).set_color(WHITE)
arrow['data-B_in'] = mkVGroup(circuit, [25]).set_color(WHITE)
arrow['data-B_out'] = mkVGroup(circuit, [29]).set_color(WHITE)
arrow['data-instr_in'] = mkVGroup(circuit, [26]).set_color(WHITE)
arrow['instr-ctrl_in'] = mkVGroup(circuit, [39]).set_color(WHITE)
arrow['ctrl-instr_in'] = mkVGroup(circuit, [36]).set_color(WHITE)
arrow['ctrl-regA_in'] = mkVGroup(circuit, [34]).set_color(WHITE)
arrow['ctrl-regB_in'] = mkVGroup(circuit, [35]).set_color(WHITE)
arrow['ctrl-pcnt_in'] = mkVGroup(circuit, [37]).set_color(WHITE)
arrow['instr-ALU_in'] = mkVGroup(circuit, [38]).set_color(WHITE)
arrow['data-mem_in'] = mkVGroup(circuit, [23]).set_color(WHITE)
arrow['data-mem_out'] = mkVGroup(circuit, [31]).set_color(WHITE)
arrow['data-pcnt_in'] = mkVGroup(circuit, [32]).set_color(WHITE)
arrow['regA-ALU_in'] = mkVGroup(circuit, [28]).set_color(WHITE)
arrow['regB-ALU_in'] = mkVGroup(circuit, [27]).set_color(WHITE)
tmpl = TexTemplate()
tmpl.add_to_preamble(r"\usepackage{array}")
code = Tex(r"""
1 & LOAD A & \$100\\
3 & LOAD B & \$101\\
5 & ADD & A,B\\
6 & STORE & \$102\\
&\dots &\\
100 & 155 &\\
101 & 42 &\\
102 & 0 &\\
""",
tex_environment=r"{tabular}{>{\ttfamily}r>{\ttfamily}l>{\ttfamily}l}",
tex_template=tmpl,
).scale_to_fit_width(0.65*comp['memory'].width).move_to(comp['memory'][0])
codelines = VGroup(
VGroup( # load A
code[0][0],
code[0][1:6],
),
VGroup( # load A
code[0][0],
code[0][6:10],
),
VGroup( # load B
code[0][10],
code[0][11:16],
),
VGroup( # load B
code[0][10],
code[0][16:20],
), #*******************
VGroup( # add a,b
code[0][20],
code[0][21:27],
),
VGroup( # store
code[0][27],
code[0][28:33],
),
VGroup(
code[0][27],
code[0][33:37],
),
VGroup(
code[0][40:43],
code[0][43:46],
),
VGroup(
code[0][46:49],
code[0][49:51],
),
VGroup(
code[0][51:54],
code[0][54],
),
)
for c in comp:
self.add(comp[c])
self.add(code)
pcnt = Integer(1, font_size=22).move_to(comp['pcnt'][0])
self.add(pcnt)
# ===================================================
def signal_pcnt():
self.play(
Indicate(comp['ctrl-pcnt'],scale_factor=1),
Indicate(arrow['ctrl-pcnt_in'],scale_factor=1)
)
self.remove(arrow['ctrl-pcnt_in'])
def signal_to_instr():
self.play(
Indicate(comp['ctrl-instr'],scale_factor=1),
Indicate(arrow['ctrl-instr_in'],scale_factor=1)
)
self.remove(arrow['ctrl-instr_in'])
def signal_to_regA():
self.play(
Indicate(comp['ctrl-regA'],scale_factor=1),
Indicate(arrow['ctrl-regA_in'],scale_factor=1)
)
self.remove(arrow['ctrl-regA_in'])
def signal_to_regB():
self.play(
Indicate(comp['ctrl-regB'],scale_factor=1),
Indicate(arrow['ctrl-regB_in'],scale_factor=1)
)
self.remove(arrow['ctrl-regB_in'])
def act_regA():
self.add(arrow['ctrl-regA_in'])
self.play(
comp['ctrl-regA'].animate.set_color(YELLOW),
arrow['ctrl-regA_in'].animate.set_color(YELLOW)
)
def deact_regA():
self.play(
comp['ctrl-regA'].animate.set_color(WHITE),
arrow['ctrl-regA_in'].animate.set_color(WHITE)
)
self.remove(arrow['ctrl-regA_in'])
def act_regB():
self.add(arrow['ctrl-regB_in'])
self.play(
comp['ctrl-regB'].animate.set_color(YELLOW),
arrow['ctrl-regB_in'].animate.set_color(YELLOW)
)
def deact_regB():
self.play(
comp['ctrl-regB'].animate.set_color(WHITE),
arrow['ctrl-regB_in'].animate.set_color(WHITE)
)
self.remove(arrow['ctrl-regB_in'])
def act_ctrl_instr():
self.add(arrow['ctrl-instr_in'])
self.play(
comp['ctrl-instr'].animate.set_color(YELLOW),
arrow['ctrl-instr_in'].animate.set_color(YELLOW)
)
def deact_ctrl_instr():
self.play(
comp['ctrl-instr'].animate.set_color(WHITE),
arrow['ctrl-instr_in'].animate.set_color(WHITE)
)
self.remove(arrow['ctrl-instr_in'])
def act_instr_ctrl():
self.add(arrow['instr-ctrl_in'])
self.play(
comp['instr-ctrl'].animate.set_color(YELLOW),
arrow['instr-ctrl_in'].animate.set_color(YELLOW)
)
def deact_instr_ctrl():
self.play(
comp['instr-ctrl'].animate.set_color(WHITE),
arrow['instr-ctrl_in'].animate.set_color(WHITE)
)
self.remove(arrow['instr-ctrl_in'])
def act_instr_ALU():
self.add(arrow['instr-ALU_in'])
self.play(
comp['instr-ALU'].animate.set_color(YELLOW),
arrow['instr-ALU_in'].animate.set_color(YELLOW)
)
def deact_instr_ALU():
self.play(
comp['instr-ALU'].animate.set_color(WHITE),
arrow['instr-ALU_in'].animate.set_color(WHITE)
)
self.remove(arrow['instr-ALU_in'])
def act_result_data():
self.add(arrow['result-data_in'])
self.play(
comp['result-data'].animate.set_color(YELLOW),
arrow['result-data_out'].animate.set_color(YELLOW)
)
def deact_result_data():
self.play(
comp['result-data'].animate.set_color(WHITE),
arrow['result-data_out'].animate.set_color(WHITE)
)
self.remove(arrow['rsult-data_out'])
p_adr = mkPath([
comp['adrbus'][0].get_start()+.2*LEFT,
comp['adrbus'][0].get_end()+.2*UL,
comp['adrbus'][1].get_end()+.2*UL,
])
def act_adrbus(obj):
self.add(arrow['adr-mem_in'])
comp['adrbus'].set_color(YELLOW)
arrow['adr-mem_in'].set_color(YELLOW)
self.play(MoveAlongPath(obj, p_adr), run_time=2)
def clear_adrbus(obj):
comp['adrbus'].set_color(WHITE)
arrow['adr-mem_in'].set_color(WHITE)
self.remove(obj, arrow['adr-mem_in'])
# ===================================================
# LADDA A -> instr
signal_pcnt()
d1 = pcnt.copy()
act_adrbus(d1)
self.play(codelines[0].animate.set_color(YELLOW).scale(1.1))
d2 = codelines[0][1].copy()
p_mem_inst = mkPath([
d2.get_center(),
comp['data-mem'][0].get_start(),
comp['data-mem'][0].get_end(),
comp['data-instr'][0].get_end(),
comp['data-instr'][0].get_start(),
comp['instruction'][0].get_center(),
]
)
act_ctrl_instr()
self.add(arrow['data-mem_out'],arrow['data-instr_in'])
self.play(MoveAlongPath(d2, p_mem_inst), run_time=2)
self.remove(arrow['data-mem_out'],arrow['data-instr_in'])
deact_ctrl_instr()
act_instr_ctrl()
clear_adrbus(d1)
self.play(codelines[0].animate.set_color(WHITE).scale(1/1.1))
# read argument -> pcnt
signal_pcnt()
self.play(pcnt.animate.set_value(2))
d1 = pcnt.copy()
act_adrbus(d1)
self.play(codelines[1].animate.set_color(YELLOW).scale(1.1))
d3 = codelines[1][1][1:].copy()
p_mem_pcnt = mkPath([
d3.get_center(),
comp['data-mem'][0].get_start(),
comp['data-mem'][0].get_end(),
comp['data-pcnt'][0].get_start(),
comp['data-pcnt'][0].get_end(),
comp['pcnt'][0].get_center()+RIGHT,
]
)
self.add(arrow['data-mem_out'],arrow['data-pcnt_in'])
self.play(MoveAlongPath(d3, p_mem_pcnt), run_time=2)
self.remove(arrow['data-mem_out'],arrow['data-pcnt_in'])
clear_adrbus(d1)
# read from address
signal_pcnt()
self.play(VGroup(d3,pcnt).animate.shift(LEFT))
act_adrbus(d3)
self.play(codelines[1].animate.set_color(WHITE).scale(1/1.1))
self.play(codelines[7].animate.set_color(YELLOW).scale(1.1))
d4 = codelines[7][1].copy()
p_mem_A = mkPath([
d4.get_center(),
comp['data-mem'][0].get_start(),
comp['data-mem'][0].get_end(),
comp['data-A'][0].get_end(),
comp['data-A'][0].get_start(),
comp['regA'][0].get_center(),
]
)
act_regA()
self.add(arrow['data-mem_out'],arrow['data-A_in'])
self.play(MoveAlongPath(d4, p_mem_A), run_time=2)
self.remove(arrow['data-mem_out'],arrow['data-A_in'])
deact_regA()
deact_instr_ctrl()
self.play(FadeOut(d2))
clear_adrbus(d3)
self.play(codelines[7].animate.set_color(WHITE).scale(1/1.1))
self.play(pcnt.animate.shift(RIGHT))
# step pcnt
signal_pcnt()
self.play(pcnt.animate.set_value(3))
# LADDA B -> instr
d1 = pcnt.copy()
act_adrbus(d1)
self.play(codelines[2].animate.set_color(YELLOW).scale(1.1))
d2 = codelines[2][1].copy()
p_mem_inst = mkPath([
d2.get_center(),
comp['data-mem'][0].get_start(),
comp['data-mem'][0].get_end(),
comp['data-instr'][0].get_end(),
comp['data-instr'][0].get_start(),
comp['instruction'][0].get_center(),
]
)
act_ctrl_instr()
self.add(arrow['data-mem_out'],arrow['data-instr_in'])
self.play(MoveAlongPath(d2, p_mem_inst), run_time=2)
self.remove(arrow['data-mem_out'],arrow['data-instr_in'])
deact_ctrl_instr()
act_instr_ctrl()
clear_adrbus(d1)
self.play(codelines[2].animate.set_color(WHITE).scale(1/1.1))
# read argument -> pcnt
signal_pcnt()
self.play(pcnt.animate.set_value(4))
d1 = pcnt.copy()
act_adrbus(d1)
self.play(codelines[3].animate.set_color(YELLOW).scale(1.1))
d3 = codelines[3][1][1:].copy()
p_mem_pcnt = mkPath([
d3.get_center(),
comp['data-mem'][0].get_start(),
comp['data-mem'][0].get_end(),
comp['data-pcnt'][0].get_start(),
comp['data-pcnt'][0].get_end(),
comp['pcnt'][0].get_center()+RIGHT,
]
)
self.add(arrow['data-mem_out'],arrow['data-pcnt_in'])
self.play(MoveAlongPath(d3, p_mem_pcnt), run_time=2)
self.remove(arrow['data-mem_out'],arrow['data-pcnt_in'])
clear_adrbus(d1)
self.play(codelines[3].animate.set_color(WHITE).scale(1/1.1))
# read from address
signal_pcnt()
self.play(VGroup(d3,pcnt).animate.shift(LEFT))
act_adrbus(d3)
self.play(codelines[8].animate.set_color(YELLOW).scale(1.1))
d5 = codelines[8][1].copy()
p_mem_B = mkPath([
d5.get_center(),
comp['data-mem'][0].get_start(),
comp['data-mem'][0].get_end(),
comp['data-B'][0].get_end(),
comp['data-B'][0].get_start(),
comp['regB'][0].get_center(),
]
)
act_regB()
self.add(arrow['data-mem_out'],arrow['data-B_in'])
self.play(MoveAlongPath(d5, p_mem_B), run_time=2)
self.remove(arrow['data-mem_out'],arrow['data-B_in'])
deact_regB()
deact_instr_ctrl()
self.play(FadeOut(d2))
clear_adrbus(d3)
self.play(codelines[8].animate.set_color(WHITE).scale(1/1.1))
# step pcnt
signal_pcnt()
self.play(pcnt.animate.shift(RIGHT))
self.play(pcnt.animate.set_value(5))
# ADD A,B -> instr
d1 = pcnt.copy()
act_adrbus(d1)
self.play(codelines[4].animate.set_color(YELLOW).scale(1.1))
d2 = codelines[4][1].copy()
p_mem_inst = mkPath([
d2.get_center(),
comp['data-mem'][0].get_start(),
comp['data-mem'][0].get_end(),
comp['data-instr'][0].get_end(),
comp['data-instr'][0].get_start(),
comp['instruction'][0].get_center(),
]
)
act_ctrl_instr()
self.add(arrow['data-mem_out'],arrow['data-instr_in'])
self.play(MoveAlongPath(d2, p_mem_inst), run_time=2)
self.remove(arrow['data-mem_out'],arrow['data-instr_in'])
deact_ctrl_instr()
act_instr_ALU()
act_instr_ctrl()
self.add(arrow['regA-ALU_in'],arrow['regB-ALU_in'])
result = Integer(197, font_size=22).next_to(comp['result-data'],UP,aligned_edge=RIGHT,buff=0.1)
self.play(Create(result))
self.remove(arrow['regA-ALU_in'],arrow['regB-ALU_in'])
deact_instr_ALU()
deact_instr_ctrl()
self.play(FadeOut(d2))
clear_adrbus(d1)
self.play(codelines[4].animate.set_color(WHITE).scale(1/1.1))
# SKRIV
self.play(pcnt.animate.set_value(6))
# SKRIV -> instr
d1 = pcnt.copy()
act_adrbus(d1)
self.play(codelines[5].animate.set_color(YELLOW).scale(1.1))
d2 = codelines[5][1].copy()
p_mem_inst = mkPath([
d2.get_center(),
comp['data-mem'][0].get_start(),
comp['data-mem'][0].get_end(),
comp['data-instr'][0].get_end(),
comp['data-instr'][0].get_start(),
comp['instruction'][0].get_center(),
]
)
act_ctrl_instr()
self.add(arrow['data-mem_out'],arrow['data-instr_in'])
self.play(MoveAlongPath(d2, p_mem_inst), run_time=2)
self.remove(arrow['data-mem_out'],arrow['data-instr_in'])
deact_ctrl_instr()
act_instr_ctrl()
clear_adrbus(d1)
self.play(codelines[5].animate.set_color(WHITE).scale(1/1.1))
# read argument -> pcnt
signal_pcnt()
self.play(pcnt.animate.set_value(7))
d1 = pcnt.copy()
act_adrbus(d1)
self.play(codelines[6].animate.set_color(YELLOW).scale(1.1))
d3 = codelines[6][1][1:].copy()
p_mem_pcnt = mkPath([
d3.get_center(),
comp['data-mem'][0].get_start(),
comp['data-mem'][0].get_end(),
comp['data-pcnt'][0].get_start(),
comp['data-pcnt'][0].get_end(),
comp['pcnt'][0].get_center()+RIGHT,
]
)
self.add(arrow['data-mem_out'],arrow['data-pcnt_in'])
self.play(MoveAlongPath(d3, p_mem_pcnt), run_time=2)
self.remove(arrow['data-mem_out'],arrow['data-pcnt_in'])
clear_adrbus(d1)
self.play(codelines[6].animate.set_color(WHITE).scale(1/1.1))
#--
signal_pcnt()
self.play(VGroup(d3,pcnt).animate.shift(LEFT))
act_adrbus(d3)
self.play(codelines[9].animate.set_color(YELLOW).scale(1.1))
#--
p_ALU_mem = mkPath([
result.get_center(),
comp['result-data'][0].get_end()+0.1*UR,
comp['result-data'][1].get_end()+0.1*UR,
comp['result-data'][2].get_end()+0.1*UP,
comp['data-mem'][0].get_end(),
comp['data-mem'][0].get_start(),
codelines[9][1].get_right(),
]
)
self.add(arrow['data-mem_in'],arrow['result-data_out'])
self.play(
codelines[9][1].animate(run_time=1).set_opacity(0),
MoveAlongPath(result, p_ALU_mem), run_time=2
)
self.remove(arrow['data-mem_in'],arrow['result-data_out'])
self.play(codelines[9].animate.set_color(WHITE).scale(1/1.1))
clear_adrbus(d3)
self.play(FadeOut(d2))
deact_instr_ctrl()
# --------------------------------------------------
self.wait(3)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment