Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228import React, { useId, useState } from "react";import { ArrowRight, Info, BookOpen, Lightbulb, Warning,} from "@phosphor-icons/react";import { Markdown } from "./Markdown.jsx";import { parseLearningBlock, translateAddress,} from "./shared/learning-blocks.js";
function AddressTranslation({ block }) { const [address, setAddress] = useState(block.address), [draft, setDraft] = useState(String(block.address)), [activeRole, setActiveRole] = useState(null); const uid = useId(), max = block.pageSize * block.mappings.length - 1; const result = translateAddress(address, block.pageSize, block.mappings); const change = (value) => { const n = Number(value); setDraft(value); if (value !== "" && Number.isSafeInteger(n) && n >= 0 && n <= max) setAddress(n); }; const update = (n) => { setAddress(n); setDraft(String(n)); }; const part = (role) => ({ onMouseEnter: () => setActiveRole(role), onMouseLeave: () => setActiveRole(null), onFocus: () => setActiveRole(role), onBlur: () => setActiveRole(null), }); return ( <figure className="learning-figure address-translation" data-active-role={activeRole || ""} > <div className="figure-heading"> <span className="figure-number">Figure</span> <span>Address translation</span> </div> <div className="translation-controls"> <label htmlFor={uid}> Virtual address <input id={uid} type="number" min={0} max={max} step={1} value={draft} onChange={(e) => change(e.target.value)} onBlur={() => setDraft(String(address))} /> </label> <label className="offset-slider"> Offset <output>{result.offset}</output> <input type="range" min={0} max={block.pageSize - 1} step={1} value={result.offset} onChange={(e) => update(result.page * block.pageSize + Number(e.target.value)) } aria-label="Offset within page" /> </label> </div> <div className="translation-grid"> <section className="translation-address"> <h4>Virtual address</h4> <div className="address-parts"> <button type="button" className="page-part" {...part("page")}> <small>Page number</small> <strong>{result.page}</strong> </button> <button type="button" className="offset-part" {...part("offset")}> <small>Offset</small> <strong>{result.offset}</strong> </button> </div> <div className="address-bits"> <span className="page-part"> {result.page .toString(2) .padStart( Math.max(1, Math.ceil(Math.log2(block.mappings.length))), "0", )} </span> <span className="offset-part"> {result.offset .toString(2) .padStart(Math.log2(block.pageSize), "0")} </span> </div> <p className="translation-description"> {block.mappings.length} virtual pages <br /> {block.pageSize.toLocaleString("en-US")} bytes per page </p> </section> <section className="translation-table"> <h4>Page table</h4> <div className="translation-table-head"> <span>Page</span> <span>Frame</span> </div> {block.mappings.map((frame, page) => ( <button type="button" key={page} className={result.page === page ? "selected" : ""} aria-pressed={result.page === page} aria-label={`Select virtual page ${page}`} onClick={() => update(page * block.pageSize + result.offset)} > <span className="page-part"> {page.toString().padStart(2, "0")} </span> <ArrowRight size={14} aria-hidden="true" /> <span> {frame === null ? "Not mapped" : frame.toString().padStart(2, "0")} </span> </button> ))} </section> <section className="translation-physical"> <h4>Physical address</h4> {result.frame === null ? ( <div className="unmapped-address"> Not mapped <span>The operating system must handle this access.</span> </div> ) : ( <> <div className="physical-frame"> <span> Frame <strong className="page-part">{result.frame}</strong> </span> <div className="frame-offset-track" aria-hidden="true"> <span style={{ left: `${(result.offset / (block.pageSize - 1)) * 100}%`, }} /> </div> <div className="frame-scale"> <span>0</span> <span>{block.pageSize - 1}</span> </div> <p> Byte <strong className="offset-part">{result.offset}</strong>{" "} within the frame </p> </div> <output className="physical-result" aria-live="polite"> <small>Physical address</small> <strong>{result.physical.toLocaleString("en-US")}</strong> </output> </> )} </section> </div> <div className="translation-equation" aria-label="Translation calculation" > {result.frame === null ? ( "No physical address for an unmapped page" ) : ( <> <span className="page-part">{result.frame}</span> <span>×</span> <span>{block.pageSize}</span> <span>+</span> <span className="offset-part">{result.offset}</span> <span>=</span> <strong>{result.physical}</strong> </> )} </div> <figcaption>{block.caption}</figcaption> </figure> );}export function LessonBlock({ code, materialId, sources }) { const block = parseLearningBlock(code); if (!block) return ( <div className="invalid-learning-block"> <p role="alert">This learning block has invalid data.</p> <pre>{code}</pre> </div> ); if (block.type === "address-translation") return <AddressTranslation key={code} block={block} />; const Icon = { note: Info, definition: BookOpen, example: Lightbulb, warning: Warning, }[block.type]; return ( <aside className={`lesson-callout ${block.type}`}> <h4> <Icon size={18} aria-hidden="true" /> {block.title} </h4> <Markdown content={block.content} materialId={materialId} sources={sources} allowLearningBlocks={false} /> </aside> );}